﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace QuailEnvironmentConfiguration
{
    /// <summary>
    /// Wraps the TestEnvironment data model and provides access to environment-specific configurations
    /// </summary>
    public class Environment
    {
        private string _name;
        private Configuration _config;

        /// <summary>
        /// Initializes a new instance of the <see cref="Environment"/> class.
        /// </summary>
        /// <param name="environmentid">The environmentid.</param>
        public Environment(int environmentid)
        {
            EnvironmentId = environmentid;
        }

        protected Environment(Environment environment)
        {
            EnvironmentId = environment.EnvironmentId;
            Name = environment.Name;
            Description = environment.Description;
            _config = environment.Config;
        }

        /// <summary>
        /// Gets the EnvironmentId for the environment
        /// </summary>
        public int EnvironmentId
        {
            get; private set;
        }

        /// <summary>
        /// Gets or sets the name for the environment
        /// </summary>
        public string Name
        {
            get
            {
                return _name;
            }
            
            internal set
            {
                _name = value;
                _config = null;
            }
        }

        /// <summary>
        /// Get or sets the environment's description
        /// </summary>
        public string Description
        {
            get;
            internal set;
        }

        /// <summary>
        /// Gets the conffiguration object for the environment
        /// </summary>
        public Configuration Config
        {
            get
            {
                if (_config == null)
                    _config = new Configuration(this)
                                  {
                                      EnableCache = true
                                  };

                return _config;
            }
        }

        private readonly object _syncThis = new object();
        private int? _activeTestCount;
        private DateTime _activeTestCountExpires = DateTime.UtcNow;
        private static readonly TimeSpan ActiveTestTimeout = new TimeSpan(0, 0, 5);

        /// <summary>
        /// Gets the current number of actively running tests.  Tests running for over an hour are ignored.
        /// </summary>
        /// <returns>The number of tests currently executing for this environment</returns>
        public int GetCurrentActiveTestCount()
        {
            lock (_syncThis)
            {
                if (!_activeTestCount.HasValue || DateTime.UtcNow >= _activeTestCountExpires)
                {
                    using (var db = QuailServices.QuailDataServiceFactory.CreateClient())
                    {
                        _activeTestCountExpires = DateTime.UtcNow + ActiveTestTimeout;
                        _activeTestCount = db.GetCurrentActiveTestCount(EnvironmentId);
                    }
                }

                return _activeTestCount.Value;
            }
        }

        /// <summary>
        /// Gets a specific environment
        /// </summary>
        /// <param name="name">the name of the environment</param>
        /// <returns>An Environment instance or NULL if the environment doesn't exist</returns>
        public static Environment GetEnvironment(string name)
        {
            using (var db = QuailServices.QuailDataServiceFactory.CreateClient())
            {
                var e = db.GetEnvironment(name);

                return e == null
                           ? null
                           : new Environment(e.TestEnvironmentId)
                                 {
                                     _name = e.EnvironmentName,
                                     Description = e.Description
                                 };
            }
        }

        /// <summary>
        /// Gets a list of all the known environments.
        /// </summary>
        /// <returns>A list of environment objects</returns>
        public static List<Environment> GetEnvironments()
        {
            using (var db = QuailServices.QuailDataServiceFactory.CreateClient())
            {
                return db.GetAllEnvironments()
                    .Select(e => new Environment(e.TestEnvironmentId)
                                     {
                                         _name = e.EnvironmentName,
                                         Description = e.Description
                                     })
                    .ToList();
            }
        }
    }
}
